zhouqijie

一、高度纹理

高度纹理(高度图)是表面凹凸的实现方法之一。(适用于高精细度模型)

※高度纹理(高度图)还可以用于生成地形。

二、法线纹理

重新计算法线的方式(在什么空间计算):

在切线空间计算。(效率高但是通用性差)
在世界空间计算。(需要构建TtoW变换矩阵)(建议在顶点着色器中构建)
在视图空间计算。(需要构建TtoV变换矩阵)

补充:切线的属性:

切线方向Tangent对应纹理坐标的U。副切线Binormal对应纹理坐标的V。

补充:顶点切线计算:

已知:

=>

=>

推导出:

代码实现:

glm::vec3 GetTangent(vec3 pos1, vec3 pos2, vec3 pos3, vec2 uv1, vec2 uv2, vec2 uv3, vec3 normal)
{
	glm::vec3 tangent;

	vec3 edge1 = pos2 - pos1;
	vec3 edge2 = pos3 - pos1;
	vec2 deltaUV1 = uv2 - uv1;
	vec2 deltaUV2 = uv3 - uv1;

	GLfloat f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y);

	tangent.x = f * (deltaUV2.y * edge1.x - deltaUV1.y * edge2.x);
	tangent.y = f * (deltaUV2.y * edge1.y - deltaUV1.y * edge2.y);
	tangent.z = f * (deltaUV2.y * edge1.z - deltaUV1.y * edge2.z);
	tangent = normalize(tangent);

	//glm::vec3 bitangent;

	//bitangent.x = f * (-deltaUV2.x * edge1.x + deltaUV1.x * edge2.x);
	//bitangent.y = f * (-deltaUV2.x * edge1.y + deltaUV1.x * edge2.y);
	//bitangent.z = f * (-deltaUV2.x * edge1.z + deltaUV1.x * edge2.z);
	//bitangent = normalize(bitangent);

	return tangent;
}

(在Unity中直接在a2v结构体里用TANGENT语义声明即可使用。)

补充:TBN的施密特正交化:

TBN可能不正交,可以用施密特正交化:

vec3 T = normalize(vec3(model * vec4(tangent, 0.0)));
vec3 N = normalize(vec3(model * vec4(normal, 0.0)));
// re-orthogonalize T with respect to N
T = normalize(T - dot(T, N) * N);
// then retrieve perpendicular vector B with the cross product of T and N
vec3 B = cross(T, N);

mat3 TBN = mat3(T, B, N)